/*
 * @Author: “ygnnli” “1585923072@qq.com”
 * @Date: 2024-08-04 21:01:20
 * @LastEditors: “ygnnli” “1585923072@qq.com”
 * @LastEditTime: 2024-08-05 09:50:46
 * @FilePath: /110/54/net_cal/Protocol.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include <sys/types.h>
#include <unistd.h>

namespace protocol_ns
{
    const std::string SEP = "\r\n";
    // "len"\r\n"_x _op _y"\r\n  -> len: 有效载荷的长度，约定\r\n是分隔符，不参与统计
    // 添加报头 len\r\n -> len: 有效载荷的长度，约定\r\n是分隔符，不参与统计
    std::string Encode(const std::string &json_str)
    {
        int json_str_len = json_str.size(); // 获取json字符串的长度
        std::string proto_str = std::to_string(json_str_len);
        proto_str += SEP;
        proto_str += json_str;
        proto_str += SEP;

        return proto_str;
    }
    // 情况：1、报头没有接收完整
    // 情况：2、报头接收完整，但是有效载荷没有接收完整
    // 情况：3、报头和有效载荷都接收完整
    //  "len"\r\n"{
    //  "len"\r\n"{             }"
    //  "len"\r\n"{             }"\r\n;
    //  "len"\r\n"{             }"\r\n"len";
    //  "len"\r\n"{             }"\r\n"len"\r\n"{             }";
    //  "len"\r\n"{             }"\r\n"len"\r\n"{             }"\r\n
    //  解析报头，获取有效载荷的长度，然后接收有效载荷
    std::string Decode(std::string &inbuffer)
    {
        auto pos = inbuffer.find(SEP); // 找到第一个分隔符
        if (pos == std::string::npos)
            return std::string();                      // 没有找到分隔符，说明报头没有接收完整
        std::string len_str = inbuffer.substr(0, pos); // 获取报头的长度
        if (len_str.empty())
            return std::string();         // 报头为空，说明报头没有接收完整
        int packlen = std::stoi(len_str); // 将报头的长度转换为int类型

        int total = packlen + len_str.size() + 2 * SEP.size(); // 报头+有效载荷+两个分隔符---总长度
        if (inbuffer.size() < total)
            return std::string(); // 如果接收到的数据长度小于总长度，说明有效载荷没有接收完整

        std::string package = inbuffer.substr(pos + SEP.size(), packlen); // 获取有效载荷
        inbuffer.erase(0, total);                                         // 将已经解析的数据从缓冲区中删除
        return package;
    }

    // 就是结构化数据 能像网络中直接发送吗？不能，也不建议，因为网络传输是字节流，需要序列化
    class Request
    {
    public:
        // 我们的协议的样子 :
        // 报文 = 报头+有效载荷
        // "有效载荷的长度"\r\n"有效载荷"\r\n
        // "len"\r\n"_x _op _y"\r\n  -> len: 有效载荷的长度，约定\r\n是分隔符，不参与统计

        // 客户端发送给服务器的数据
        Request()
        {
        }
        // 协议
        Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
        {
        }
        // 序列化：将数据结构化数据转换为字节流
        bool Serialize(std::string *out)
        {
            // 转换成为字符串
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["oper"] = _oper;

            Json::FastWriter writer; // 序列化
            // Json::StyledWriter writer;
            *out = writer.write(root);

            return true;
        }
        // 反序列化：将字节流转换为结构化数据
        bool Deserialize(const std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)
                return false;

            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt(); // 没有char类型，所以用int

            return true;
        }

    public:
        int _x;
        int _y;
        char _oper; // + - * /  _x _oper _y
    };
    // 服务器发送给客户端的数据
    class Response
    {
    public:
        Response()
        {
        }
        //
        Response(int result, int code) : _result(result), _code(code)
        {
        }
        // 序列化：将数据结构化数据转换为字节流
        bool Serialize(std::string *out)
        {
            // 转换成为字符串
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            Json::FastWriter writer; // 序列化
            // Json::StyledWriter writer;
            *out = writer.write(root);

            return true;
        }
        // 反序列化：将字节流转换为结构化数据
        bool Deserialize(const std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (!res)
                return false;

            _result = root["result"].asInt();
            _code = root["code"].asInt();

            return true;
        }

    public:
        int _result; // 结果
        int _code;   // 0:success 1: 除0 2: 非法操作 3. 4. 5
    };

    class Factory
    {
    public:
        Factory()
        {
            srand(time(nullptr) ^ getpid()); // 随机数种子
            opers = "+-*/%^&|";
        }
        ~Factory() {}
        std::shared_ptr<Request> BuildRequest()
        {
            int x = rand() % 10 + 1;
            usleep(x * 10);
            int y = rand() % 5;
            usleep(y * x * 5);
            char oper = opers[rand() % opers.size()]; // 随机运算符

            std::shared_ptr<Request> req = std::make_shared<Request>(x, y, oper); // 创建请求对象
            return req;
        }

        std::shared_ptr<Response> BuildResponse()
        {
            return std::make_shared<Response>();
        }

    private:
        std::string opers;
    };

}
